package org.szy.plugin.dev.service.impl;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.util.UpdateEntity;
import org.noear.solon.Utils;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.ProxyComponent;
import org.noear.solon.core.handle.UploadedFile;
import org.szy.core.common.exception.BaseException;
import org.szy.core.common.page.QueryPage;
import org.szy.core.common.prop.FileProperties;
import org.szy.core.common.service.FileService;
import org.szy.core.common.service.impl.BaseServiceImpl;
import org.szy.core.common.uilts.FileUploadUtils;
import org.szy.plugin.dev.entity.DevFile;
import org.szy.plugin.dev.mapper.DevFileMapper;
import org.szy.plugin.dev.param.DevFileQueryParam;
import org.szy.plugin.dev.param.DevFileUploadParam;
import org.szy.plugin.dev.service.DevFileService;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

import static org.szy.plugin.dev.entity.table.DevFileTableDef.DEV_FILE;

/**
 * 开发_文件Service接口实现类
 *
 * @author wangbuhao
 * @since 2023-06-28 18:17:40
 **/
@ProxyComponent
public class DevFileServiceImpl extends BaseServiceImpl<DevFileMapper, DevFile> implements DevFileService {

    @Inject
    private DevFileMapper devFileMapper;
    @Inject
    private FileService fileService;

    @Override
    public QueryWrapper qwByQuery(DevFileQueryParam param) {
        QueryWrapper qw = new QueryWrapper();
        if (StrUtil.isNotEmpty(param.getColumnField())) {
            qw.select(param.getColumnField().split(","));
        }
        qw.and(DEV_FILE.ORIGINAL_NAME.like(param.getOriginalName()));
        qw.and(DEV_FILE.APPLY_TO.eq(param.getApplyTo()));
        qw.and(DEV_FILE.APPLY_TO.in(StrUtil.splitTrim(param.getApplyToIn(), ",")));
        qw.and(DEV_FILE.REF_NUM.eq(param.getRefNum()));
        qw.and(DEV_FILE.REF_NUM.in(StrUtil.splitTrim(param.getRefNumIn(), ",")));
        qw.and(DEV_FILE.CATEGORY.eq(param.getCategory()));
        qw.and(DEV_FILE.CATEGORY.in(StrUtil.splitTrim(param.getCategoryIn(), ",")));
        qw.orderBy(DEV_FILE.UPDATE_TIME.desc());

        return qw;
    }

    @Override
    public Page<DevFile> page(QueryPage<DevFile> page, DevFileQueryParam param) {
        QueryWrapper qw = qwByQuery(param);

        // 正序排序
        if (StrUtil.isNotEmpty(page.getAscField())) qw.orderBy(page.getAscField().split(","));
        // 倒叙排序
        if (StrUtil.isNotEmpty(page.getDescField())) {
            for (String desc : page.getDescField().split(",")) {
                qw.orderBy(new QueryColumn(desc).desc());
            }
        }

        return this.page(page, qw);
    }

    @Override
    public List<DevFile> list(DevFileQueryParam param) {
        QueryWrapper qw = qwByQuery(param);
        return list(qw);
    }

    @Override
    public boolean removeById(Serializable id) {
        DevFile file = getById(id, "storage_path");
        boolean remove = super.removeById(id);
        // TODO 将文件移动到 删除的文件夹,后续做成定时器
        Utils.async(() -> {
            if (StrUtil.isNotEmpty(file.getStoragePath()) && FileUtil.exist(file.getStoragePath())) {
                String storagePath = StrUtil.replace(file.getStoragePath(), FileProperties.localFilePath, FileProperties.localRemovePath);
                FileUtil.move(FileUtil.file(file.getStoragePath()), FileUtil.file(storagePath), true);
                String sql = "update dev_file set storage_path= ? where id = ?";
                Db.updateBySql(sql, storagePath, id);
            }
        });
        return remove;
    }

    @Override
    public DevFile upload(UploadedFile file, DevFileUploadParam devFileUploadParam) {
        try {
            String fileUrl = fileService.uploadFile(file);
            String filePath = FileProperties.localFilePath;
            if (FileProperties.enableDomain) {
                filePath = filePath + fileUrl.replace(FileProperties.domain, "").replace(FileProperties.localFilePrefix, "");
            } else {
                filePath = filePath + fileUrl.replace(FileProperties.localFilePrefix, "");
            }
            DevFile devFile = new DevFile();
            devFile.setCategory(devFileUploadParam.getCategory());
            devFile.setApplyTo(devFileUploadParam.getApplyTo());
            devFile.setRefNum(devFileUploadParam.getRefNum());
            devFile.setNetworkPath(fileUrl);
            devFile.setStoragePath(filePath);
            devFile.setOriginalName(file.getName());
            devFile.setName(file.getName());
            devFile.setSizeKb(Convert.toStr(NumberUtil.div(new BigDecimal(file.getContentSize()), BigDecimal.valueOf(1024))
                    .setScale(0, RoundingMode.HALF_UP)));
            devFile.setSizeInfo(FileUtil.readableFileSize(file.getContentSize()));
            devFile.setSuffix(FileUploadUtils.getExtension(file));
            devFile.setType(FileUtil.getMimeType(filePath));
            save(devFile);
            return devFile;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("上传文件失败，原因：" + e.getMessage());
        }
    }

    @Override
    public boolean modifyRefNumByApplyAndRef(String applyTo, Long refNum, Long targetNum) {
        DevFile of = UpdateEntity.of(DevFile.class);
        QueryWrapper qw = new QueryWrapper();
        qw.and(DEV_FILE.APPLY_TO.eq(applyTo)).and(DEV_FILE.REF_NUM.eq(refNum));
        of.setRefNum(targetNum);
        return update(of, qw);
    }

    @Override
    public List<DevFile> listByApplyAndRef(String applyTo, Long refNum) {
        return null;
    }

    @Override
    public List<DevFile> listByApplyAndRefAndCategory(String applyTo, Long refNum, String category) {
        return null;
    }
}
